<template>
  <div
    class="m-form"
    v-if="formModel"
  >
    <el-form
      v-bind="$attrs"
      ref="elFormRef"
      :validate-on-rule-change="false"
      :model="formModel"
      :rules="formRule"
    >
      <template
        v-for="(item, index) in options"
        :key="index"
      >
        <el-form-item
          v-if="!item.children || !item.children.length"
          :label="item.label"
          :prop="item.prop"
          :rules="{validator: item.validator, trigger: 'blur'}"
        >
          <el-upload
            v-bind="{...(item.uploadAttrs || {}), ...(item.uploadMethods || {})}"
            v-if="item.type === 'upload'"
            :on-success="onSuccess"
          >
            <el-button
              size="small"
              type="primary"
            >Click to upload</el-button>
            <template #tip>
              <div class="el-upload__tip">
                jpg/png files with a size less than 500kb
              </div>
            </template>
          </el-upload>
          <div
            v-else-if="item.type === 'editor'"
            :id="item.prop"
          ></div>
          <template v-else>
            <component
              v-bind="item.attrs"
              v-if="!item.slotName"
              v-model="formModel[item.prop]"
              :placeholder="item.placeholder"
              :is="`el-${item.type}`"
            >
            </component>
            <slot
              v-else
              :name="item.slotName"
              :item="item"
              :model="formModel"
            ></slot>
          </template>

        </el-form-item>
        <el-form-item
          v-if="item.children && item.children.length"
          :label="item.label"
          :prop="item.prop"
        >
          <component
            v-bind="item.attrs"
            v-model="formModel[item.prop]"
            :placeholder="item.placeholder"
            :is="`el-${item.type}`"
          >
            <component
              v-bind="item.attrs"
              v-for="(child, i) in item.children"
              :key="i"
              :is="`el-${child.type}`"
              :label="child.label"
              :value="child.value"
            ></component>
          </component>
        </el-form-item>
      </template>
      <el-form-item>
        <slot name="action"></slot>
      </el-form-item>
    </el-form>

  </div>
</template>

<script lang="ts" setup>
import { onMounted, PropType, ref, watch, nextTick } from "vue";
import { FormOptions } from "../types/types";
import cloneDeep from "lodash/cloneDeep";
import { ElForm } from "element-plus";
import E from "wangeditor";
const props = defineProps({
  options: {
    type: Array as PropType<FormOptions[]>,
    required: true,
  },
});
const formModel = ref<any>(null);
const formRule = ref<any>(null);
const editorMap = ref<any>({});
const elFormRef = ref<InstanceType<typeof ElForm>>();
// 初始化表单
const initForm = () => {
  if (props.options && props.options.length) {
    let m: any = {};
    let r: any = {};
    let e: any = {};
    props.options.forEach((item: FormOptions) => {
      m[item.prop!] = item.value;
      r[item.prop!] = item.rules;
      e[item.prop!] = {};
      if (item.type === "editor") {
        nextTick(() => {
          let domStr = item.prop;
          if (document.getElementById(domStr!)) {
            e[item.prop!].editor = new E("#" + domStr);
            e[item.prop!].editor.config.placeholder = item.placeholder;
            e[item.prop!].editor.config.onchangeTimeout = 500;
            e[item.prop!].editor.create();
            e[item.prop!].editor.txt.html(item.value);
            e[item.prop!].editor.config.onchange = (value: string) => {
              formModel.value[item.prop!] = value;
            };
          }
        });
      }
    });
    formModel.value = cloneDeep(m);
    formRule.value = cloneDeep(r);
    editorMap.value = e;
  }
};
const emits = defineEmits(["change"]);
// 表单赋值
onMounted(() => {
  initForm();
});
// 监听父组件传递选项配置变化的时候重新渲染表单
watch(
  () => props.options,
  () => {
    initForm();
  },
  {
    deep: true,
  }
);
watch(
  () => formModel.value,
  (val) => {
    emits("change", cloneDeep(val));
  },
  {
    deep: true,
  }
);

// 重置方法
const resetFields = () => {
  console.log("resetFields");
  // 单独重置一下富文本编辑内容
  const editors = props.options.filter((r) => r.type === "editor");
  const uploads = props.options.filter((r) => r.type === "upload");
  if (editors.length) {
    editors.forEach((r) => {
      editorMap.value[r.prop!].editor.txt.html(r.value);
    });
  }
  if (uploads.length) {
    uploads.forEach((r) => {
      //formModel.value[r?.prop!]
    });
  }
  elFormRef.value?.resetFields();
};
const submitForm = () => {
  console.log("submitForm", elFormRef.value);
  return new Promise((resolve, reject) => {
    if (formRule.value) {
      elFormRef.value?.validate((valid) => {
        if (valid) {
          resolve(true);
        } else {
          reject(false);
        }
      });
    } else {
      resolve(true);
    }
  });
};
const clearValidate = (key: string | any[]) => {
  elFormRef.value?.clearValidate(key);
};

const onSuccess = (response: any, file: File, fileList: FileList) => {
  const uploadItem = props.options.find((r) => r.type === "upload");
  formModel.value[uploadItem?.prop!] = { response, file, fileList };
};
defineExpose({
  resetFields,
  submitForm,
  clearValidate,
});
</script>

<style>
</style>